package com.microservice.common.config;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.codec.Decoder;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

/**
 * Feign配置
 * 自动传递Token到下游服务
 * 配置支持泛型嵌套的解码器
 */
@Slf4j
@Configuration
public class FeignConfig {
    
    /**
     * Feign请求拦截器
     * 自动将当前请求的Authorization头传递给下游服务
     */
    @Bean
    public RequestInterceptor requestInterceptor() {
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate template) {
                // 获取当前请求的HttpServletRequest
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                
                if (attributes != null) {
                    HttpServletRequest request = attributes.getRequest();
                    
                    // 获取当前请求的Authorization头
                    String token = request.getHeader("Authorization");
                    
                    if (token != null && !token.isEmpty()) {
                        // 将Token传递到Feign请求中
                        template.header("Authorization", token);
                        log.debug("Feign调用自动传递Token: {}", template.url());
                    } else {
                        log.debug("Feign调用未检测到Token: {}", template.url());
                    }
                } else {
                    log.debug("Feign调用无法获取请求上下文: {}", template.url());
                }
            }
        };
    }
    
    /**
     * 配置Feign解码器
     * 解决泛型嵌套反序列化问题（如Result<PageResult<DTO>>）
     * 解决日期格式解析问题
     */
    @Bean
    public Decoder feignDecoder() {
        ObjectMapper objectMapper = createObjectMapper();
        
        // 创建支持泛型的HttpMessageConverter
        MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(objectMapper);
        
        ObjectFactory<HttpMessageConverters> messageConverters = () -> {
            HttpMessageConverter<?> converter = jacksonConverter;
            return new HttpMessageConverters(converter);
        };
        
        return new SpringDecoder(messageConverters);
    }
    
    /**
     * 创建配置好的ObjectMapper
     * 统一JSON序列化和反序列化配置
     */
    private ObjectMapper createObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        
        // === 基础配置 ===
        // 忽略未知属性，避免JSON字段不匹配导致的错误
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 接受空字符串作为null对象
        objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
        // 允许接受单个值作为数组
        objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        
        // === 日期时间配置 ===
        // 禁用将日期写为时间戳
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        // 设置日期格式：支持 "yyyy-MM-dd HH:mm:ss" 格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        objectMapper.setDateFormat(dateFormat);
        
        // 注册Java 8时间模块（支持LocalDateTime等）
        objectMapper.registerModule(new JavaTimeModule());
        
        // 设置时区
        objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        
        log.info("Feign ObjectMapper配置完成：支持日期格式 yyyy-MM-dd HH:mm:ss");
        
        return objectMapper;
    }
}
